<template>
  <div style="padding: 20px">
    <el-button @click="drawType('line')">画折线</el-button>
    <el-button @click="drawType('square')">画矩形</el-button>
    <el-button @click="clearAll">清除画布</el-button>
    <div style="width: 1200px; height: 800px" class="canvas-wrap">
      <img src="@/assets/images/1693530676345.jpg" />
      <canvas
        id="canvas"
        style="cursor: grab"
        @mousedown.prevent="handleMouseDown"
        @mousemove.prevent="handleMouseMove"
        @mouseup.prevent="handleMouseUp"
      ></canvas>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { reactive, onMounted, onBeforeUnmount } from 'vue'
const state = reactive({
  ctx: null,
  type: '',
  drawStatus: false, // 绘制状态
  timer: null,
  tempPointArr: [], //临时存储画点
  pointData: [],
  squarePoint: null // 存储矩形点位
})

const init = () => {
  const canvas = document.getElementById('canvas') as any
  canvas.width = 1200
  canvas.height = 800
  state.ctx = canvas.getContext('2d')
}

const drawType = (type) => {
  state.type = type
  clearAll()
}

// 画折线(左键绘制，右键终止保存数据)
const drawLine = (e) => {
  if (e.button === 0) {
    state.drawStatus = true
    state.timer && clearTimeout(state.timer)
    state.timer = setTimeout(() => {
      state.tempPointArr.push({ x: e.offsetX, y: e.offsetY })
      if (state.tempPointArr.length <= 1) return
      state.ctx.strokeStyle = '#FF0000'
      state.ctx.lineWidth = 4
      state.ctx.beginPath()
      state.ctx.moveTo(
        state.tempPointArr[state.tempPointArr.length - 2].x,
        state.tempPointArr[state.tempPointArr.length - 2].y
      )
      state.ctx.lineTo(
        state.tempPointArr[state.tempPointArr.length - 1].x,
        state.tempPointArr[state.tempPointArr.length - 1].y
      )
      state.ctx.stroke()
    }, 100)
  } else if (e.button === 2) {
    state.ctx.clearRect(0, 0, 1200, 800)
    echoTempPoint(state.tempPointArr)
    state.tempPointArr.length && (state.pointData = state.tempPointArr)
    state.tempPointArr = []
    state.drawStatus = false
    console.log(state.pointData)
  }
}

// 画矩形
const drawSquare = (e) => {
  if (e.button === 2) return
  state.drawStatus = true
  state.squarePoint = { x1: e.offsetX, y1: e.offsetY, x2: 0, y2: 0 }
}

// 鼠标按下
const handleMouseDown = (e) => {
  if (state.type === 'line') {
    drawLine(e)
  } else {
    drawSquare(e)
  }
}

// 鼠标抬起
const handleMouseUp = (e) => {
  if (state.type === 'line') return
  if (!state.squarePoint || e.offsetX === state.squarePoint.x1 || e.offsetY === state.squarePoint.y1) {
    state.squarePoint = null
    state.drawStatus = false
    return
  }
  state.drawStatus = false
  state.squarePoint.x2 = e.offsetX
  state.squarePoint.y2 = e.offsetY
  state.pointData = state.squarePoint
  state.squarePoint = null
  console.log(state.pointData)
}

// 实现线跟随鼠标移动
const handleMouseMove = (e) => {
  if (!state.drawStatus) return
  state.ctx.clearRect(0, 0, 1200, 800)
  if (state.type === 'line') {
    if (!state.tempPointArr.length) return
    echoTempPoint(state.tempPointArr)
    state.ctx.strokeStyle = '#FF0000'
    state.ctx.lineWidth = 4
    state.ctx.beginPath()
    state.ctx.moveTo(
      state.tempPointArr[state.tempPointArr.length - 1].x,
      state.tempPointArr[state.tempPointArr.length - 1].y
    )
    state.ctx.lineTo(e.offsetX, e.offsetY)
    state.ctx.stroke()
  } else {
    state.ctx.strokeStyle = '#FF0000'
    state.ctx.lineWidth = 4
    state.ctx.beginPath()
    state.ctx.strokeRect(
      state.squarePoint.x1,
      state.squarePoint.y1,
      e.offsetX - state.squarePoint.x1,
      e.offsetY - state.squarePoint.y1
    )
  }
}

// 回显之前画的点之间的连线
const echoTempPoint = (cur) => {
  for (let i = 1; i < cur.length; i++) {
    state.ctx.beginPath()
    state.ctx.strokeStyle = '#FF0000'
    state.ctx.lineWidth = 4
    state.ctx.moveTo(cur[i - 1].x, cur[i - 1].y)
    state.ctx.lineTo(cur[i].x, cur[i].y)
    state.ctx.stroke()
  }
}

// 清除数据
const clearAll = () => {
  state.ctx.clearRect(0, 0, 1200, 800)
  state.drawStatus = false
  state.pointData = null
  state.tempPointArr = []
  state.timer = null
}

const disableContextMenu = (e) => {
  e.preventDefault()
}

onMounted(() => {
  init()
  document.addEventListener('contextmenu', disableContextMenu)
})

onBeforeUnmount(() => {
  document.removeEventListener('contextmenu', disableContextMenu)
})
</script>

<style lang="scss" scoped>
.canvas-wrap {
  position: relative;
  img {
    display: block;
    width: 100%;
    height: 100%;
  }
  canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}
</style>
